import numpy as np
import numpy
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA,KernelPCA
from sklearn.datasets import make_circles
from sklearn.neural_network import BernoulliRBM
import theano
import theano.tensor as T
from theano.tensor.shared_randomstreams import RandomStreams
from dA import dA

def plot2d(X,Y,ax):
	for (x,y) in zip(X,Y):
		if y == 1:
			ax.plot(x[0],x[1],'ro')
		else: 
			ax.plot(x[0],x[1],'b*')

r=1
r2=5
n=200
theta=[2.0*np.pi*v/n for v in range(n)]
#print theta
x=r*np.sin(theta)
y=r*np.cos(theta)
l=[1 for v in range(n)]

a=np.transpose(np.asarray([x,y,l]))

x2=r2*np.sin(theta)
y2=r2*np.cos(theta)
l2=[0 for v in range(n)]

b=np.transpose(np.asarray([x2,y2,l2]))
c=np.concatenate((a,b))
X=c[:,:-1]
Y=c[:,-1]
print a.shape
print b.shape
print c.shape

np.random.seed(0)
X, Y = make_circles(n_samples=n, factor=.3, noise=.05)

fig, ax=plt.subplots(2,4)
[(ax1,ax2,ax3,ax4),(ax5,ax6,ax7,ax8)]=ax
#ax.plot(x,y,'ro')
#ax.plot(x2,y2,'b*')
#ax.plot(c[:,0],c[:,1],'ro')
plot2d(X,Y,ax1)
#ax1.plot(X[:,0],X[:,1],'ro')

pca = PCA(n_components=2)
X_pca=pca.fit_transform(X)
plot2d(X_pca,Y,ax2)

kpca = KernelPCA(kernel="rbf", fit_inverse_transform=True, gamma=10)
X_kpca = kpca.fit_transform(X)
plot2d(X_kpca,Y,ax3)

#rbm = BernoulliRBM(n_components=10)
#X_rbm = rbm.fit_transform(X)
#plot2d(X_rbm,Y,ax4)

def dae_trans(X,Y,learning_rate=0.00003, training_epochs=15,
            batch_size=1,corruption_level=0.1,nv=2,nh=2):
    #from dA import dA
    train_set_x = theano.shared(numpy.asarray(X,dtype=theano.config.floatX), borrow=True)
    index = T.lscalar() # index to a [mini]batch
    x = T.matrix('x')  # the data is presented as rasterized images
    rng = numpy.random.RandomState(123)
    theano_rng = RandomStreams(rng.randint(2 ** 30))

    n_train_batches = train_set_x.get_value(borrow=True).shape[0] / batch_size
    da = dA(numpy_rng=rng, theano_rng=theano_rng, input=x,
            n_visible=nv, n_hidden=nh)
    
    cost, updates = da.get_cost_updates(corruption_level=corruption_level,
                                        learning_rate=learning_rate)
    train_da = theano.function([index], cost, updates=updates,
         givens={x: train_set_x[index * batch_size:
                                  (index + 1) * batch_size]})
    for epoch in xrange(training_epochs):
        # go through trainng set
        c = []
        for batch_index in xrange(n_train_batches):
            c.append(train_da(batch_index))
        print 'Training epoch %d, cost ' % epoch, numpy.mean(c)

    return da.transform(X,corruption_level=corruption_level)

plot2d(X,Y,ax4)

def dae_l1(X,Y,ax,corruption_level=0.0):
    l1=dae_trans(X,Y,corruption_level=corruption_level,nv=2,nh=10)[0]
    #l2=dae_trans(l1,Y,corruption_level=corruption_level)[0]
    print len(l1)
    print len(l1[0])
    #ax.set_xlim(-0.1,1.1)
    #ax.set_ylim(-0.1,1.1)
    plot2d(l1,Y,ax)

def dae_l2(X,Y,ax,corruption_level=0.0):
    l1=dae_trans(X,Y,corruption_level=corruption_level)[0]
    l2=dae_trans(l1,Y,corruption_level=corruption_level)[0]
    ax.set_xlim(-0.1,1.1)
    ax.set_ylim(-0.1,1.1)
    plot2d(l2,Y,ax)

def dae_l3(X,Y,ax,corruption_level=0.0):
    l1=dae_trans(X,Y,corruption_level=corruption_level,nv=2,nh=10)[0]
    l2=dae_trans(l1,Y,corruption_level=corruption_level,nv=10,nh=10)[0]
    l3=dae_trans(l2,Y,corruption_level=corruption_level,nv=10,nh=2)[0]
    ax.set_xlim(-0.1,1.1)
    ax.set_ylim(-0.1,1.1)
    plot2d(l3,Y,ax)

dae_l1(X,Y,ax5,corruption_level=0.0)
dae_l1(X,Y,ax6,corruption_level=0.1)
dae_l1(X,Y,ax7,corruption_level=0.2)
dae_l1(X,Y,ax8,corruption_level=0.5)
'''
X_dae=dae_trans(X,Y,corruption_level=0.0)[0]
#print len(X_dae)
#print len(X_dae[0])
#print len(X_dae[0][0])
ax5.set_xlim(-0.1,1.1)
ax5.set_ylim(-0.1,1.1)
plot2d(X_dae,Y,ax5)

X_dae=dae_trans(X,Y,corruption_level=0.1)[0]
#print len(X_dae)
#print len(X_dae[0])
#print len(X_dae[0][0])
ax6.set_xlim(-0.1,1.1)
ax6.set_ylim(-0.1,1.1)
plot2d(X_dae,Y,ax6)

X_dae=dae_trans(X,Y,corruption_level=0.2)[0]
#print len(X_dae)
#print len(X_dae[0])
#print len(X_dae[0][0])
ax7.set_xlim(-0.1,1.1)
ax7.set_ylim(-0.1,1.1)
plot2d(X_dae,Y,ax7)

X_dae=dae_trans(X,Y,corruption_level=0.5)[0]
ax8.set_xlim(-0.1,1.1)
ax8.set_ylim(-0.1,1.1)
plot2d(X_dae,Y,ax8)
'''
plt.show()
